/*
 *  libKara - Library for basic instant messaging functions
 *  Copyright (C) 2007-2008 Markus Karnik
 *
 *  This program is free software; you can redistribute it and/or modify it 
 *  under the terms of the GNU General Public License as published by the
 *  Free Software Foundation; either version 3 of the License, 
 *  or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
 *  for more details.
 *
 *  You should have received a copy of the GNU General Public License along 
 *  with this program; if not, see <http://www.gnu.org/licenses/>.
 *  
 */

package de.karnik.libkara;

import java.util.Vector;

import de.karnik.helper.LogFunctions;
import de.karnik.libkara.pluginspecs.BaseProtocol;
import de.karnik.libkara.pluginspecs.ProtocolListener;
import de.karnik.libkara.pluginspecs.ProtocolSettings;
import de.karnik.libkara.proto.ProtocolException;
import de.karnik.libkara.proto.xmpp.XmppProtocol;
import de.karnik.libkara.proto.xmpp.XmppSettings;
import de.karnik.libkara.roster.ImContact;
import de.karnik.libkara.roster.ImContactListener;
import de.karnik.libkara.roster.ImMessage;
import de.karnik.libkara.roster.ImRoster;

/**
 * The account class implements the important account functions.
 * 
 * @author Markus Karnik - markus.karnik@my-design.org
 * @version 1.0
 * @since 1.0
 */
public class ImAccount implements ProtocolListener, ImContactListener {

	/**
	 * Type undefined protocol type.
	 */
	public static final int TYPE_UNDEF = 0;
	/**
	 * Type XMPP protocol type.
	 */
	public static final int TYPE_XMPP = 1;
	/**
	 * Type oscar protocol type.
	 */
	public static final int TYPE_OSCAR = 2;
	
	/**
	 * The protocol type.
	 */
	private int type = TYPE_UNDEF;
	/**
	 * The account id.
	 */
	private String id = null;
	/**
	 * The protocol settings object.
	 */
	private ProtocolSettings protoSettings = null;
	/**
	 * The protocol object.
	 */
	private BaseProtocol protocol = null;
	/**
	 * The active indicator.
	 */
	private boolean active = false;
	
	/**
	 * The contacts storage.
	 */
	private Vector<ImContact> contacts = new Vector<ImContact>();

	/**
	 * Constructs an account based on the given settings.
	 * 
	 * @param settings The protocol settings to use.
	 * @throws ProtocolException
	 */
	public ImAccount( ProtocolSettings settings ) throws ProtocolException {
		
		this.protoSettings = settings;
		
		if( this.protoSettings instanceof XmppSettings ) {
			XmppSettings xmppSettings = ( XmppSettings )this.protoSettings;	
			protocol = new XmppProtocol();
			
			this.id = xmppSettings.getStringData( XmppSettings.STRING_VALUE_USERID ) 
						+ "@" + xmppSettings.getStringData( XmppSettings.STRING_VALUE_HOSTNAME );
			protocol.setAccountID( this.id );
			protocol.proto_configure( xmppSettings );
			protocol.addProtocolListener( this );
			
			this.type = TYPE_XMPP;
		}
	}
	
	/**
	 * Sets the protocol listener.
	 * 
	 * @param listener The protocol listener to set.
	 */
	public void setProtocolListener( ProtocolListener listener ) {
		this.protocol.addProtocolListener( listener );
	}

	/**
	 * Returns the protocol settings.
	 * 
	 * @return The protocol settings.
	 */
	public ProtocolSettings getProtoSettings() {
		return protoSettings;
	}

	/**
	 * Returns the is active indicator.
	 * 
	 * @return <b>true</b> if account is active, <b>false</b> otherwise.
	 */
	public boolean isActive() {
		return active;
	}

	/**
	 * Sets the is active indicator.
	 * 
	 * @param active <b>true</b> if account is active, <b>false</b> otherwise.
	 */
	public void setActive( boolean active ) {
		this.active = active;
	}

	/**
	 * Returns the accounts protocol.
	 * 
	 * @return The accounts protocol.
	 */
	public BaseProtocol getProtocol() {
		return protocol;
	}

	/**
	 * Sets the account protocol.
	 * 
	 * @param protocol The protocol to set.
	 */
	public void setProtocol( BaseProtocol protocol ) {
		this.protocol = protocol;
	}

	/**
	 * Returns the protocol type.
	 * 
	 * @return The protocol type.
	 */
	public int getType() {
		return type;
	}

	/**
	 * Returns the protocol id.
	 * 
	 * @return The protocol id.
	 */
	public String getId() {
		return id;
	}

	/* (non-Javadoc)
	 * @see de.karnik.libkara.pluginspecs.ProtocolListener#connected(java.lang.String)
	 */
	public void connected( String accountID ) {}
	/* (non-Javadoc)
	 * @see de.karnik.libkara.pluginspecs.ProtocolListener#disconnected(java.lang.String)
	 */
	public void disconnected( String accountID ) {}

	/* (non-Javadoc)
	 * @see de.karnik.libkara.pluginspecs.ProtocolListener#contactReceived(de.karnik.libkara.roster.ImContact)
	 */
	public void contactReceived( ImContact contact ) {
		LogFunctions.log( "ImAccount.contactReceived","contact received", contact.getUserID() );
		contact.addContactListener( this );
		ImRoster roster = ImRoster.getInstance();
		roster.addImContact( contact );
		this.contacts.add( contact );
		
	}

	/* (non-Javadoc)
	 * @see de.karnik.libkara.pluginspecs.ProtocolListener#contactStatusChanged(java.lang.String, int, java.lang.String)
	 */
	public void contactStatusChanged( String userID, int status, String statusMessage ) {
		for( int i = 0; i < this.contacts.size(); i++ ) {
			if( this.contacts.get( i ).getUserID().toLowerCase().equals( userID.toLowerCase() ) ) {
				this.contacts.get( i ).setUserStatus( status );
				if( statusMessage != null )
					this.contacts.get( i ).setUserStatusMessage( statusMessage );
			}
		}
		ImRoster.getInstance().rebuildRoster();
		
	}

	/* (non-Javadoc)
	 * @see de.karnik.libkara.pluginspecs.ProtocolListener#messageArrived(java.lang.String, de.karnik.libkara.roster.ImMessage)
	 */
	public void messageArrived( String userID, ImMessage message ) {
		// add the incoming message to the sending contact-object 
		for( int i = 0; i < this.contacts.size(); i++ ) {
			if( this.contacts.get( i ).getUserID().equalsIgnoreCase( userID ) )
				this.contacts.get( i ).addIncomingMessage( message );
		}
		ImRoster.getInstance().rebuildRoster();
	}

	/* (non-Javadoc)
	 * @see de.karnik.libkara.pluginspecs.ProtocolListener#rosterReceived()
	 */
	public void rosterReceived() {
		// send presence to every user to refresh status etc
		for( int i = 0; i < this.contacts.size(); i++ )
			try {
				this.protocol.proto_refreshContactStatus( this.contacts.get( i ) );
			} catch (ProtocolException e) {
				LogFunctions.log( e.getMessage() );
			}
			
	}

	/* (non-Javadoc)
	 * @see de.karnik.libkara.roster.ImContactListener#incomingMessageArrived(de.karnik.libkara.roster.ImMessage)
	 */
	public void incomingMessageArrived( ImContact contact, ImMessage message ) {}

	/* (non-Javadoc)
	 * @see de.karnik.libkara.roster.ImContactListener#messageArrived()
	 */
	public void messageArrived() {}

	/* (non-Javadoc)
	 * @see de.karnik.libkara.roster.ImContactListener#outgoingMessageArrived(de.karnik.libkara.roster.ImMessage)
	 */
	public void outgoingMessageArrived( ImContact contact, ImMessage message ) {
		try {
			this.protocol.proto_sendMessage( contact , message );
		} catch ( ProtocolException e ) {
			LogFunctions.log( e.getMessage() );
		}
	}

	/* (non-Javadoc)
	 * @see de.karnik.libkara.roster.ImContactListener#authProcessFinished()
	 */
	public void authProcessFinished() {}
	/* (non-Javadoc)
	 * @see de.karnik.libkara.roster.ImContactListener#authProcessStarted()
	 */
	public void authProcessStarted() {}
	
}
